use tauri::{AppHandle, Manager};
use std::path::PathBuf;
use sha2::{Sha256, Digest};
use base64::{Engine as _, engine::general_purpose};

/// 获取应用数据目录路径，并确保目录存在
fn ensure_app_data_dir(app: &AppHandle) -> Result<PathBuf, String> {
    let dir = app.path()
        .app_data_dir()
        .map_err(|e| format!("获取应用数据目录失败: {}", e))?;
    
    // 使用同步方式创建目录（更可靠）
    std::fs::create_dir_all(&dir)
        .map_err(|e| format!("创建应用数据目录失败: {} (路径: {})", e, dir.display()))?;
    
    // 验证目录是否真的存在
    if !dir.exists() {
        return Err(format!("应用数据目录创建后仍不存在: {}", dir.display()));
    }
    
    // 验证目录是否可写
    if !dir.is_dir() {
        return Err(format!("应用数据目录路径不是目录: {}", dir.display()));
    }
    
    Ok(dir)
}

/// 获取存储文件路径
/// 使用 key 的 SHA256 哈希作为文件名，避免特殊字符问题
fn get_storage_path(app: &AppHandle, key: &str) -> Result<PathBuf, String> {
    let mut path = ensure_app_data_dir(app)?;
    
    // 使用 key 的哈希作为文件名（避免特殊字符问题）
    let mut hasher = Sha256::new();
    hasher.update(key.as_bytes());
    let hash = hasher.finalize();
    let filename = general_purpose::STANDARD.encode(hash);
    path.push(format!("{}.json", filename));
    Ok(path)
}

/// 安全存储数据
#[tauri::command]
pub async fn secure_store_set(
    key: String,
    value: String,
    app: AppHandle,
) -> Result<(), String> {
    let path = get_storage_path(&app, &key)?;
    
    // 再次确保父目录存在（双重保险）
    if let Some(parent) = path.parent() {
        if !parent.exists() {
            std::fs::create_dir_all(parent)
                .map_err(|e| format!("创建父目录失败: {} (路径: {})", e, parent.display()))?;
        }
    }
    
    // 写入文件
    tokio::fs::write(&path, value)
        .await
        .map_err(|e| format!("写入文件失败: {} (路径: {}, 父目录存在: {})", 
            e, 
            path.display(),
            path.parent().map(|p| p.exists()).unwrap_or(false)))?;
    
    Ok(())
}

/// 安全读取数据
#[tauri::command]
pub async fn secure_store_get(
    key: String,
    app: AppHandle,
) -> Result<Option<String>, String> {
    let path = get_storage_path(&app, &key)?;
    
    // 检查文件是否存在
    if !path.exists() {
        return Ok(None);
    }
    
    // 读取文件
    match tokio::fs::read_to_string(&path).await {
        Ok(content) => {
            Ok(Some(content))
        },
        Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
            Ok(None)
        },
        Err(e) => {
            Err(format!("读取文件失败: {}", e))
        },
    }
}

/// 安全删除数据
#[tauri::command]
pub async fn secure_store_remove(
    key: String,
    app: AppHandle,
) -> Result<(), String> {
    let path = get_storage_path(&app, &key)?;
    
    // 删除文件
    if path.exists() {
        tokio::fs::remove_file(&path)
            .await
            .map_err(|e| format!("删除文件失败: {}", e))?;
    }
    
    Ok(())
}

/// 清理所有缓存数据
/// 删除应用数据目录下的所有文件（包括聊天记录、群组缓存、用户数据等）
#[tauri::command]
pub async fn clear_all_cache(
    app: AppHandle,
) -> Result<u32, String> {
    let data_dir = app
        .path()
        .app_data_dir()
        .map_err(|e| format!("获取应用数据目录失败: {}", e))?;
    
    if !data_dir.exists() {
        return Ok(0);
    }
    
    let mut deleted_count = 0u32;
    
    // 遍历目录中的所有文件
    if let Ok(entries) = std::fs::read_dir(&data_dir) {
        for entry in entries {
            if let Ok(entry) = entry {
                let path = entry.path();
                if path.is_file() {
                    // 删除文件
                    if tokio::fs::remove_file(&path).await.is_ok() {
                        deleted_count += 1;
                    }
                }
            }
        }
    }
    
    Ok(deleted_count)
}

/// 获取图片缓存目录路径
fn get_image_cache_dir(app: &AppHandle) -> Result<PathBuf, String> {
    let mut dir = ensure_app_data_dir(app)?;
    dir.push("image_cache");
    std::fs::create_dir_all(&dir)
        .map_err(|e| format!("创建图片缓存目录失败: {}", e))?;
    Ok(dir)
}

/// 获取缓存的图片路径
#[tauri::command]
pub async fn get_cached_image_path(
    cache_key: String,
    app: AppHandle,
) -> Result<Option<String>, String> {
    let cache_dir = get_image_cache_dir(&app)?;
    
    // 尝试多种图片格式
    let extensions = vec!["jpg", "jpeg", "png", "gif", "webp", "bmp", "svg"];
    
    for ext in extensions {
        let mut image_path = cache_dir.clone();
        image_path.push(format!("{}.{}", cache_key, ext));
        
        if image_path.exists() {
            // 返回文件路径（前端会使用 convertFileSrc 转换）
            return Ok(Some(image_path.to_string_lossy().to_string()));
        }
    }
    
    Ok(None)
}

/// 获取缓存的图片数据（返回 base64 data URI）
#[tauri::command]
pub async fn get_cached_image_data(
    cache_key: String,
    app: AppHandle,
) -> Result<Option<String>, String> {
    let cache_dir = get_image_cache_dir(&app)?;
    
    // 尝试多种图片格式
    let extensions = vec!["jpg", "jpeg", "png", "gif", "webp", "bmp", "svg"];
    
    for ext in extensions {
        let mut image_path = cache_dir.clone();
        image_path.push(format!("{}.{}", cache_key, ext));
        
        if image_path.exists() {
            // 读取文件内容
            let image_data = tokio::fs::read(&image_path)
                .await
                .map_err(|e| format!("读取图片文件失败: {}", e))?;
            
            // 编码为 base64
            let base64_data = general_purpose::STANDARD.encode(&image_data);
            
            // 根据文件扩展名确定 MIME 类型
            let mime_type = match ext {
                "png" => "image/png",
                "gif" => "image/gif",
                "webp" => "image/webp",
                "bmp" => "image/bmp",
                "svg" => "image/svg+xml",
                _ => "image/jpeg", // jpg, jpeg 或其他
            };
            
            // 返回 base64 data URI
            return Ok(Some(format!("data:{};base64,{}", mime_type, base64_data)));
        }
    }
    
    Ok(None)
}

/// 缓存图片
#[tauri::command]
pub async fn cache_image(
    cache_key: String,
    base64_data: String,
    content_type: String,
    app: AppHandle,
) -> Result<String, String> {
    let cache_dir = get_image_cache_dir(&app)?;
    let mut image_path = cache_dir;
    
    // 根据内容类型确定文件扩展名
    let extension = match content_type.as_str() {
        "image/png" => "png",
        "image/gif" => "gif",
        "image/webp" => "webp",
        "image/bmp" => "bmp",
        "image/svg+xml" => "svg",
        _ => "jpg", // 默认使用 jpg
    };
    
    image_path.push(format!("{}.{}", cache_key, extension));
    
    // 解码 base64 数据
    let image_data = general_purpose::STANDARD
        .decode(&base64_data)
        .map_err(|e| format!("解码 base64 数据失败: {}", e))?;
    
    // 写入文件
    tokio::fs::write(&image_path, image_data)
        .await
        .map_err(|e| format!("写入图片文件失败: {}", e))?;
    
    // 返回文件路径
    Ok(image_path.to_string_lossy().to_string())
}

/// 清理图片缓存
#[tauri::command]
pub async fn clear_image_cache(
    app: AppHandle,
) -> Result<u32, String> {
    let cache_dir = get_image_cache_dir(&app)?;
    
    if !cache_dir.exists() {
        return Ok(0);
    }
    
    let mut deleted_count = 0u32;
    
    // 遍历目录中的所有文件
    if let Ok(entries) = std::fs::read_dir(&cache_dir) {
        for entry in entries {
            if let Ok(entry) = entry {
                let path = entry.path();
                if path.is_file() {
                    // 删除文件
                    if tokio::fs::remove_file(&path).await.is_ok() {
                        deleted_count += 1;
                    }
                }
            }
        }
    }
    
    Ok(deleted_count)
}

